package com.xapp.utils.httpUtil;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import com.xapp.utils.ConstantUils;
import com.xapp.utils.SharedPreferencesUtils;
import com.xapp.yhEntities.ImageInfoEntity;
import com.xapp.yhEntities.MessageEvent;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;


/**
 * @author YH_CK
 * describe okhttp网路工具类
 **/
public class HttpRequestUtils {
    private static HttpRequestUtils mInstance;
    private static final MediaType MEDIA_TYPE = MediaType.parse("image/png");
    private OkHttpClient mOkHttpClient;
    private MessageEvent messageEvent;
    private Context mContext;
    private OkHttpClient.Builder mClientBuilder;
    private static SSLSocketFactory PINNED_FACTORY;
    private static ArrayList<Certificate> PINNED_CERTS;
    private String mHeaderJSon;

    private HttpRequestUtils(Context context) {

        mClientBuilder = new OkHttpClient.Builder();
        mClientBuilder.readTimeout(60, TimeUnit.SECONDS);//读取超时
        mClientBuilder.connectTimeout(60, TimeUnit.SECONDS);//连接超时
        mClientBuilder.writeTimeout(60, TimeUnit.SECONDS);////写入超时

        //支持HTTPS请求，跳过证书验证
//          mClientBuilder.sslSocketFactory(TrustAllCerts.createSSLSocketFactory(),new TrustAllCerts());
//        mClientBuilder.sslSocketFactory(HttpRequestUtils.getPinnedFactory(), new TrustAllCerts());

        mClientBuilder.hostnameVerifier(new TrustAllCerts.TrustAllHostnameVerifier());
        mOkHttpClient = mClientBuilder.build();
        messageEvent = new MessageEvent();
        this.mContext = context;
        this.mHeaderJSon = "";
    }


    /**
     * 单例模式获取NetUtils
     */
    public static HttpRequestUtils getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new HttpRequestUtils(context);
        }
        return mInstance;
    }

    /**
     * 自定义网络回调接口x
     */
    public interface MyNetCall {
        void success(Call call, Response response) throws IOException, JSONException;

        void failed(Call call, IOException e);
    }

    public void setAuthHeader(String header) {
        try {
            if (!header.equals("")) {
                //解析数据
                JSONObject headerJson = new JSONObject(header);
                if (headerJson.has("appUserToken")) {
                    mHeaderJSon = headerJson.getString("appUserToken");
                }
            } else {
                try {
                    String tokenCode = (String) SharedPreferencesUtils.getParam(mContext, "signature", "");
                    JSONObject useToken = new JSONObject();
                    useToken.put("userToken", tokenCode);
                    mHeaderJSon = useToken.toString();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    /**
     * post请求，异步方式，提交数据，是在子线程中执行的，需要切换到主线程才能更新UI
     */
    public void postDataAsynToNet(String url, String bodyParams, final MyNetCall myNetCall) {
        Log.i("HTTP-Post-url", url);
        //1构造RequestBody
        RequestBody body = FormBody.create(ConstantUils.JsonType, bodyParams);
        //2 构造Request
        Request.Builder requestBuilder = new Request.Builder();
        Request request = requestBuilder.addHeader("appUserToken", mHeaderJSon.toString()).post(body).url(url).build();
        //3 将Request封装为Call
        Call call = mOkHttpClient.newCall(request);
        //4 执行Call
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                myNetCall.failed(call, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    myNetCall.success(call, response);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    /**
     * 下载文件
     */
    public void downLoadFile(String url, final MyNetCall myNetCall) {
        OkHttpClient client = new OkHttpClient.Builder().addNetworkInterceptor(new InterNetInterceptor()).build();
        //1 构造Request
        Request request = new Request.Builder()
                .url(url)
                .build();
        //2 将Request封装为Call
        Call call = client.newCall(request);
        //3 执行Call
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                myNetCall.failed(call, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                try {
                    myNetCall.success(call, response);
                } catch (JSONException e) {
                    e.printStackTrace();
                }

            }
        });
    }

    /**
     * Interceptor拦截器方法实现
     */
    public class InterNetInterceptor implements Interceptor {

        @Override
        public Response intercept(Chain chain) throws IOException {
            Response response = chain.proceed(chain.request());
            return response.newBuilder().body(new ProgressResponsBody(response.body(), new ProgBar())).build();
        }
    }

    /**
     * 进度条监听
     */
    private class ProgBar implements ProgressResponsBody.ProgressListener {

        @Override
        public void onProgress(final int mProgress, final long contentSize) {
            Log.i("**************下载进度：", String.valueOf(mProgress));
            messageEvent.setCode(1003);
            messageEvent.setMessage(String.valueOf(mProgress));
            EventBus.getDefault().post(messageEvent);

        }

        @Override
        public void onDone(long totalSize) {
            Log.i("下载完成********文件大小为：", String.valueOf(totalSize));
            messageEvent.setCode(1004);
            messageEvent.setMessage(String.valueOf(totalSize));
            EventBus.getDefault().post(messageEvent);
        }
    }

    /**
     * post的请求参数，构造RequestBody
     */
    private RequestBody setRequestBody(Map<String, String> BodyParams) {
        RequestBody body = null;
        FormBody.Builder formEncodingBuilder = new FormBody.Builder();
        if (BodyParams != null) {
            Iterator<String> iterator = BodyParams.keySet().iterator();
            String key = "";
            while (iterator.hasNext()) {
                key = iterator.next().toString();
                formEncodingBuilder.add(key, BodyParams.get(key));
                Log.d("post http", "post_Params===" + key + "====" + BodyParams.get(key));
            }
        }
        body = formEncodingBuilder.build();
        return body;

    }


    /**
     * 用于信任所有证书
     */
    public static class TrustAllCerts implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }

        public static class TrustAllHostnameVerifier implements HostnameVerifier {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        }

        public static SSLSocketFactory createSSLSocketFactory() {
            SSLSocketFactory ssfFactory = null;

            try {
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, new TrustManager[]{new TrustAllCerts()}, new SecureRandom());

                ssfFactory = sc.getSocketFactory();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return ssfFactory;
        }
    }


    /**
     * HTTP request exception whose cause is always an {@link IOException}
     */
    private static class HttpRequestException extends RuntimeException {

        private static final long serialVersionUID = -1170466989781746231L;

        /**
         * Create a new HttpRequestException with the given cause
         *
         * @param cause
         */
        public HttpRequestException(final IOException cause) {
            super(cause);
        }

        /**
         * Get {@link IOException} that triggered this request exception
         *
         * @return {@link IOException} cause
         */
        @Override
        public IOException getCause() {
            return (IOException) super.getCause();
        }
    }

    /**
     * 上传图片
     */
    public void updateFile(String jsonData, final MyNetCall myNetCall) {

        List<ImageInfoEntity> mImageInfoList = new ArrayList<>();
        try {
            JSONObject myJsonData = new JSONObject(jsonData);
            String mURL = myJsonData.getString("url");
            String params = myJsonData.optString("params");
            String mAuthHeader = myJsonData.optString("header");
            JSONObject myHeaderData = new JSONObject(mAuthHeader);
            String mHeader = myHeaderData.optString("Auth-Header");
            JSONArray mJsonArray = myJsonData.getJSONArray("imageArray");
            for (int i = 0; i < mJsonArray.length(); i++) {
                JSONObject jsonObject = (JSONObject) mJsonArray.get(i);
                ImageInfoEntity imageInfoBean = new ImageInfoEntity();
                imageInfoBean.setName(jsonObject.getString("name"));
                imageInfoBean.setPath(jsonObject.getString("path"));
                imageInfoBean.setImageParams(jsonObject.optString("params"));
                mImageInfoList.add(imageInfoBean);
            }
            MultipartBody.Builder multipartBodyBuilder = new MultipartBody.Builder();
            multipartBodyBuilder.setType(MultipartBody.FORM);
            if (!TextUtils.isEmpty(params)) {
                JSONObject jbParams = new JSONObject(params);
                for (Iterator<?> iter = jbParams.keys(); iter.hasNext(); ) {
                    Object key = iter.next();
                    multipartBodyBuilder.addFormDataPart(key.toString(), jbParams.getString(key.toString()));
                }
            }
            if (mImageInfoList.size() > 0) {
                for (ImageInfoEntity imageEnty : mImageInfoList) {
                    File file = new File(imageEnty.getPath());
                    if (file != null) {
                        if (!TextUtils.isEmpty(imageEnty.getImageParams())) {
                            JSONObject jsonParam = new JSONObject(imageEnty.getImageParams());
                            for (Iterator<?> iter = jsonParam.keys(); iter.hasNext(); ) {
                                Object key = iter.next();
                                multipartBodyBuilder.addFormDataPart(key.toString(), jsonParam.getString(key.toString()));
                            }
                        }
                        String namesAndValues = "form-data; name=" + imageEnty.getName() + "; filename=" + file.getName();
                        multipartBodyBuilder.addPart(Headers.of("Content-Disposition", namesAndValues), RequestBody.create(MEDIA_TYPE, file));
                    }
                }
            }
            //构建请求体
            RequestBody requestBody = multipartBodyBuilder.build();
            //2 构造Request
            Request.Builder requestBuilder = new Request.Builder();
            Request request = requestBuilder.addHeader("token", mHeader.toString()).post(requestBody).url(mURL).build();
            //3 将Request封装为Call
            Call call = mOkHttpClient.newCall(request);
            //4 执行Call
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.i("zee",e.toString());
                    myNetCall.failed(call, e);
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    try {
                        myNetCall.success(call, response);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
